package my.project.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import my.project.admin.entity.*;
import my.project.admin.mapper.SysUserMapper;
import my.project.admin.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import my.project.admin.utils.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author zc
 * @since 2021-05-12
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {

    @Autowired
    ISysUserService sysUserService;

    @Autowired
    ISysRoleService sysRoleService;

    @Autowired
    ISysMenuService sysMenuService;

    @Autowired
    ISysRoleMenuService sysRoleMenuService;

    @Autowired
    ISysUserRoleService sysUserRoleService;

    @Autowired
    RedisUtil redisUtil;

    @Override
    public SysUser getByUsername(String  username) {
        return this.getOne(new QueryWrapper<SysUser>().lambda().eq(SysUser::getUsername, username));
    }

    //获取用户权限（角色+菜单操作权限）
    @Override
    public String getUserAuthority(Long userId) {

        SysUser user = getById(userId);
        String authority = "";

        if (redisUtil.hasKey("GrantedAuthority:" + user.getUsername())) {
            authority = (String) redisUtil.get("GrantedAuthority:" + user.getUsername());
        } else {
            //获取角色编码
            String subSql = "select role_id from sys_user_role where user_id=" + userId;
            List<SysRole> roles = sysRoleService.list(new QueryWrapper<SysRole>().inSql("id", subSql));
            if (roles.size() > 0) {
                String roleCodes = roles.stream().map(r -> "ROLE_" + r.getCode()).collect(Collectors.joining(","));
                authority = roleCodes.concat(",");
            }
            //获取菜单操作编码
            List<SysRoleMenu> roleMenus = sysRoleMenuService.list(new QueryWrapper<SysRoleMenu>()
                    .select("distinct menu_id").inSql("role_id", subSql));
            List<Long> menuIds = roleMenus.stream().map(SysRoleMenu::getMenuId).collect(Collectors.toList());
            if (menuIds.size() > 0) {
                List<SysMenu> sysMenus = sysMenuService.listByIds(menuIds);
                String menuPerms = sysMenus.stream().map(SysMenu::getPerms).collect(Collectors.joining(","));
                authority = authority.concat(menuPerms);
            }
            //存入缓存，有效期为一小时
            redisUtil.set("GrantedAuthority:" + user.getUsername(), authority, 60*60);
        }

        return authority;
    }

    //根据用户名清除用户权限缓存
    @Override
    public void clearUserAuthorityCacheByUsername(String username) {
        redisUtil.del("GrantedAuthority:" + username);
    }

    //根据角色ID清除用户权限缓存
    @Override
    public void clearUserAuthorityCacheByRoleId(Long roleId) {
        //获取用户ID
        String subSql = "select user_id from sys_user_role where role_id=" + roleId;
        List<SysUser> users = this.list(new QueryWrapper<SysUser>().inSql("id", subSql));

        users.forEach(u -> this.clearUserAuthorityCacheByUsername(u.getUsername()));
    }

    //根据菜单ID清除用户权限缓存
    @Override
    public void clearUserAuthorityCacheByMenuId(Long menuId) {
        //获取用户ID
        String subSql = "select role_id from sys_role_menu where menu_id=" + menuId;
        List<SysUserRole> userRoles = sysUserRoleService.list(new QueryWrapper<SysUserRole>().inSql("role_id", subSql));
        List<Long> userIds = userRoles.stream().map(SysUserRole::getUserId).collect(Collectors.toList());

        List<SysUser> users = sysUserService.listByIds(userIds);
        users.forEach(u -> this.clearUserAuthorityCacheByUsername(u.getUsername()));
    }
}
